/** Logger class --------------------------**/
/** Is the base class of any logger (from http://loulou.developpez.com/tutoriels/moteur3d/partie1/#L2.1)
**/

#ifndef LOGGER_H_
#define LOGGER_H_

#include <sstream>
#include <string>
#include <iostream>
#include <fstream>
#include "Exceptions.h"
#include <boost/shared_ptr.hpp>
#include <boost/lexical_cast.hpp>

namespace BPL
{
class Logger;
typedef boost::shared_ptr<Logger> LoggerPtr;


class Logger
{
public :

    virtual ~Logger();

    static void setLogger(LoggerPtr Logger);
    static void log(const char* Format, ...);

    static Logger& log();
    template <class T> Logger& operator <<(const T& ToLog);

protected :

    std::string currentDate() const;
    std::string currentTime() const;

private :

    virtual void write(const std::string& Message) = 0;
    static void destroy();

    static LoggerPtr mpv_instance; // Pointeur sur le logger actuel

 };


    template <class T> Logger& Logger::operator <<(const T& ToLog)
    {
        std::ostringstream Stream;
        Stream << ToLog;
        write(Stream.str());

        return log();
    }
}
/// ---------------------  BASIC LOGGER ---------------------- ///
class ConsoleLogger : public BPL::Logger
{
public:
    ConsoleLogger()
    {
        std::string str = "  *******************************************" ;
        str += "\n";
        str += "  ConsoleLog - Event log - " + currentDate() + "\n";
        str += "  *******************************************\n\n";

        #ifdef DEBUG_DEFINE
        str += "\n";
        str += "DEBUG MODE";
        str += "\n\n";
        #endif

        write(str);
    }

    ~ConsoleLogger()
    {

    }

private :
    virtual void write(const std::string& message)
    {
        std::cout << message << std::endl;
    }

};

class FileLogger : public BPL::Logger
{
public:
    FileLogger(const std::string& filename) : mpv_file(filename.c_str())
    {
        if (!mpv_file)
            throw LoadingFailed(filename, "Couldn't open the file");

        mpv_file << "  *******************************************" << std::endl;
        mpv_file << "  FileLog - Event log - " << currentDate() << std::endl;
        mpv_file << "  *******************************************" << std::endl << std::endl;
    }

    ~FileLogger()
    {
        mpv_file << std::endl;
        mpv_file << "  *******************************************" << std::endl;
        mpv_file << "  FileLog closed at " << currentTime() << std::endl;
        mpv_file << "  *******************************************" << std::endl;
    }

private:
    virtual void write(const std::string& message)
    {
        Assert(mpv_file.is_open());

        mpv_file << message << std::endl;
    }

    std::ofstream mpv_file;
};


#endif // LOGGER_H
